﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Milo.Framework
{
    public class ModelControl<TModel> : Control, IModelControl<TModel>
    {
        private TModel model;
		private int index;
        private GetPropertyDelegate<TModel> valueGetter;
        private SetPropertyDelegate<TModel> valueSetter;

        #region constructors
		public ModelControl() { }
        /// <summary>
        /// Initializes a new instance of the <see cref="FieldControl&lt;FieldType&gt;"/> class.
        /// <para>Initialises the control directly with the model object</para>
        /// </summary>
        /// <param name="model">The model.</param>
        public ModelControl(TModel model) { this.model = model; }
        /// <summary>
        /// Initializes a new instance of the <see cref="FieldControl&lt;FieldType&gt;"/> class.
        /// <para>Initialises the control directly with the model object as well as the Control name.
        /// This will act as a container name for any child controls</para>
        /// </summary>
        /// <param name="name">The name.</param>
        /// <param name="model">The model.</param>
        public ModelControl(string name, TModel model) : this(model) { Name = name; }
        #endregion

		#region IModelControl<TModel> Members

		public virtual TModel Value
		{
			get { return Parent == null || valueGetter == null ? model : valueGetter(index); }
			set { if (Parent == null || valueSetter == null) model = value; else valueSetter(model, index); }
		}

		public void LinkToParent(string name, IControl parent)
		{
			LinkToParent(name, parent, null, null, 0);
		}

		public void LinkToParent(string name, IControl parent, GetPropertyDelegate<TModel> valueGetter, SetPropertyDelegate<TModel> valueSetter, int index)
		{
			this.Name = name;
			this.Parent = parent;
			this.valueGetter = valueGetter;
			this.valueSetter = valueSetter;
			this.index = index;
		}

		#endregion

        public override Type GetModelType()
        {
            return typeof(TModel);
        }

		/// <summary>
		/// Returns a <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </summary>
		/// <returns>
		/// A <see cref="T:System.String"/> that represents the current <see cref="T:System.Object"/>.
		/// </returns>
		public override string ToString()
		{
			try
			{
				return Value.ToString();
			}
			catch (NullReferenceException)
			{
				return string.Empty;
			}
		}

		public virtual string ToString(string mask)
		{
			try
			{
				return string.Format(mask, Value);
			}
			catch (NullReferenceException)
			{
				return string.Empty;
			}
		}
		public virtual string ToString(string mask, string nullOrEmptySubstitution)
		{
			try
			{
				return string.Format(mask, Value);
			}
			catch (NullReferenceException)
			{
				return nullOrEmptySubstitution;
			}
		}
	}
}
